/**       
 * @{#} EvictionTimer.java Create on 2012-3-29 下午3:14:06       
 *       
 * Copyright (c) 2012 by able.       
 */
package __javable.core.util.pool.impl;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 
 * 
 * @history <PRE>
 * --------------------------------------------------------- 
 * VERSION       DATE            BY       CHANGE/COMMENT 
 * --------------------------------------------------------- 
 * 1.0           2012-3-29      able         create 
 * ---------------------------------------------------------
 * </PRE>
 * 
 */
class EvictionTimer {

	/** Timer instance */
	private static Timer _timer; // @GuardedBy("this")

	/** Static usage count tracker */
	private static int _usageCount; // @GuardedBy("this")

	/** Prevent instantiation */
	private EvictionTimer() {
		// Hide the default constuctor
	}

	/**
	 * Add the specified eviction task to the timer. Tasks that are added with a
	 * call to this method *must* call {@link #cancel(TimerTask)} to cancel the
	 * task to prevent memory and/or thread leaks in application server
	 * environments.
	 * 
	 * @param task
	 *            Task to be scheduled
	 * @param delay
	 *            Delay in milliseconds before task is executed
	 * @param period
	 *            Time in milliseconds between executions
	 */
	static synchronized void schedule(TimerTask task, long delay, long period) {
		if (null == _timer) {
			// Force the new Timer thread to be created with a context class
			// loader set to the class loader that loaded this library
			ClassLoader ccl = AccessController.doPrivileged(new PrivilegedGetTccl());
			try {
				AccessController.doPrivileged(new PrivilegedSetTccl(EvictionTimer.class.getClassLoader()));
				_timer = new Timer("commons-pool-EvictionTimer", true);
			} finally {
				AccessController.doPrivileged(new PrivilegedSetTccl(ccl));
			}
		}
		_usageCount++;
		_timer.schedule(task, delay, period);
	}

	/**
	 * Remove the specified eviction task from the timer.
	 * 
	 * @param task
	 *            Task to be scheduled
	 */
	static synchronized void cancel(TimerTask task) {
		task.cancel();
		_usageCount--;
		if (_usageCount == 0) {
			_timer.cancel();
			_timer = null;
		}
	}

	/**
	 * {@link PrivilegedAction} used to get the ContextClassLoader
	 */
	private static class PrivilegedGetTccl implements PrivilegedAction<ClassLoader> {

		/**
		 * {@inheritDoc}
		 */
		@Override
		public ClassLoader run() {
			return Thread.currentThread().getContextClassLoader();
		}
	}

	/**
	 * {@link PrivilegedAction} used to set the ContextClassLoader
	 */
	private static class PrivilegedSetTccl implements PrivilegedAction<Void> {

		/** ClassLoader */
		private final ClassLoader cl;

		/**
		 * Create a new PrivilegedSetTccl using the given classloader
		 * 
		 * @param cl
		 *            ClassLoader to use
		 */
		PrivilegedSetTccl(ClassLoader cl) {
			this.cl = cl;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Void run() {
			Thread.currentThread().setContextClassLoader(cl);
			return null;
		}
	}
}
